/* eslint-disable */
import * as CryptoJS from 'crypto-js';
import { GraphData } from '@/components/YdItRoad/itRoad-type';
// 日期格式化
export function parseTime(time: any, pattern?: any) {
	if (arguments.length === 0 || !time) {
		return null;
	}
	const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}';
	let date;
	if (typeof time === 'object') {
		date = time;
	} else {
		if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
			if (time.length > 19) {
				time = time.substring(0, 19);
			}
			time = parseInt(time);
		} else if (typeof time === 'string') {
			if (time.length > 19) {
				time = time.substring(0, 19);
			}
			time = time.replace(new RegExp(/-/gm), '/');
		}
		if (typeof time === 'number' && time.toString().length === 10) {
			time = time * 1000;
		}
		date = new Date(time);
	}
	const formatObj: {
		[prop: string]: any;
	} = {
		y: date.getFullYear(),
		m: date.getMonth() + 1,
		d: date.getDate(),
		h: date.getHours(),
		i: date.getMinutes(),
		s: date.getSeconds(),
		a: date.getDay(),
	};

	const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result: any, key: any) => {
		let value = formatObj[key];
		// Note: getDay() returns 0 on Sunday
		if (key === 'a') {
			return ['日', '一', '二', '三', '四', '五', '六'][value];
		}
		if (result.length > 0 && value < 10) {
			value = '0' + value;
		}
		return value || 0;
	});
	return time_str;
}

// 添加日期范围
export function addDateRange(params: anyObj, dateRange: any, propName?: string) {
	let search = params;
	search.params = typeof search.params === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
	dateRange = Array.isArray(dateRange) ? dateRange : [];
	if (typeof propName === 'undefined') {
		search.params['beginTime'] = dateRange[0];
		search.params['endTime'] = dateRange[1];
	} else {
		search.params['begin' + propName] = dateRange[0];
		search.params['end' + propName] = dateRange[1];
	}
	return search;
}

export function deepClone(obj: Record<string, any>) {
	// 定义一个变量 并判断是数组还是对象
	const cloneArr: Array<any> = [];
	const cloneObj: Record<string, any> = {};
	const objClone = Array.isArray(obj) ? cloneArr : cloneObj;
	if (obj && typeof obj === 'object' && obj !== null) {
		// 判断obj存在并且是对象类型的时候 因为null也是object类型，所以要单独做判断
		for (const key in obj) {
			// 循环对象类型的obj
			// 判断obj中是否存在key属性
			if (obj[key] && typeof obj[key] === 'object') {
				// 判断如果obj[key]存在并且obj[key]是对象类型的时候应该深拷贝，即在堆内存中开辟新的内存
				// if()
				objClone[key] = deepClone(obj[key]);
			} else {
				// 否则就是浅复制
				objClone[key] = obj[key];
			}
		}
	}
	return objClone;
}

/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 * @param {*} rootId 根Id 默认 0
 */
export function handleTree(data: any, id: string | number, parentId: string | number, children?: any, rootId?: ApiVal) {
	id = id || 'id';
	parentId = parentId || 'parentId';
	children = children || 'children';
	rootId = rootId || 0;
	//对源数据深度克隆
	const cloneData = JSON.parse(JSON.stringify(data));
	//循环所有项
	const treeData = cloneData.filter((father: anyObj) => {
		let branchArr = cloneData.filter((child: anyObj) => {
			//返回每一项的子级数组
			return father[id] === child[parentId];
		});
		branchArr.length > 0 ? (father.children = branchArr) : '';
		//返回第一层
		return father[parentId] === rootId;
	});
	console.log(treeData, 'treeData');
	return treeData != '' ? treeData : data;
}

/**
 * 用正则表达式实现对字符串的html转码
 *
 * @param str 要转码的字符串
 * @returns {string}
 */
export function htmlEncodeByRegExp(str: any) {
	if (str && typeof str === 'string') {
		let s = '';
		if (str.length === 0) {
			return '';
		}
		s = str.replace(/&/g, '&amp;');
		s = s.replace(/</g, '&lt;');
		s = s.replace(/>/g, '&gt;');
		s = s.replace(/ /g, '&nbsp;');
		s = s.replace(/'/g, "'");
		s = s.replace(/"/g, '"');
		s = s.replace(/\//g, '&frasl;');
		return s;
	}
	return str;
}

/**
 * 用正则表达式实现对对象某个属性的html转码
 *
 * @param row 要处理的对象
 * @param keyName 属性名
 * @returns {any}
 */
export function htmlEncodeByRegExpRow(row: any, keyName: string) {
	if (row) {
		const newRow = JSON.parse(JSON.stringify(row));
		const str = newRow[keyName];
		newRow[keyName] = htmlEncodeByRegExp(str);
		return newRow;
	}
	return row;
}

/**
 * 保留两位小数，如:2 会在后面补上00 即2.00
 * 1）  如果时长/耗时大于60000ms 则格式化为 “XX分XX.XX秒”保留两位小数
 * 2）  如果时长/耗时小于60000ms大于1000ms则格式化为“XX.XX秒”保留两位小数
 * 3）  如果时长/耗时小于1000ms则格式化为“XX.XX毫秒”保留两位小数
 * 如:
 * 204266ms  显示为  3分24.27秒
 * 2008ms    显示为  2.01秒（4舍5入）
 * 4ms       显示为  4.00毫秒（4舍5入）
 * @param data 传进来的时间
 * @param flag 标志：ms毫秒，wm微妙
 * @returns
 */
export function toDecimalFormate(data: any, flag?: any) {
	const old = data;
	if (data === null || data === undefined) {
		return 0;
	}
	if (typeof data === 'string') {
		data = parseFloat(data);
	}
	if (isNaN(data)) {
		return old;
	}

	let minute = 0;
	let second: string | number;
	let millisecond;

	if (flag === 'wm') {
		if (data >= 60000000) {
			minute = Math.floor(data / 60000000);
			second = (data % 60000000) / 1000000;
			if (second !== 0) {
				second = ((data % 60000000) / 1000000).toFixed(2);
				return minute + '分' + second + '秒';
			} else {
				return minute + '分';
			}
		} else if (data > 1000000 && data < 60000000) {
			second = Math.floor(data / 1000000).toString();
			millisecond = ((data % 1000000) / 1000000).toFixed(2);
			const num = (parseFloat(second) + parseFloat(millisecond)).toFixed(2);
			return num + '秒';
		} else {
			//毫秒计算，借用秒
			second = Math.floor(data / 1000).toString();
			millisecond = ((data % 1000) / 1000).toFixed(2);
			const num = (parseFloat(second) + parseFloat(millisecond)).toFixed(2);
			return num + '毫秒';
		}
	} else {
		if (data >= 60000) {
			minute = Math.floor(data / 60000);
			second = (data % 60000) / 1000;
			if (second !== 0) {
				second = ((data % 60000) / 1000).toFixed(2);
				return minute + '分' + second + '秒';
			} else {
				return minute + '分';
			}
		} else if (data >= 1000 && data < 60000) {
			second = Math.floor(data / 1000).toString();
			millisecond = ((data % 1000) / 1000).toFixed(2);
			const num = parseFloat((parseFloat(second) + parseFloat(millisecond)).toString()).toFixed(2);
			return num + '秒';
		} else {
			const str = data.toFixed(2);
			return str + '毫秒';
		}
	}
}

/**
 * 重载函数,结果单位为英文字母
 * 保留两位小数，如:2 会在后面补上00 即2.00
 * 1）  如果时长/耗时大于60000ms 则格式化为 “XX分XX.XX秒”保留两位小数
 * 2）  如果时长/耗时小于60000ms大于1000ms则格式化为“XX.XX秒”保留两位小数
 * 3）  如果时长/耗时小于1000ms则格式化为“XX.XX毫秒”保留两位小数
 * 如:
 * 204266ms  显示为  3m24.27s
 * 2008ms    显示为  2.01s（4舍5入）
 * 4ms       显示为  4.00ms（4舍5入）
 * @param data 传进来的时间
 * @param flag 标志：ms毫秒，wm微妙
 * @returns
 */
export function toDecimalFormate2(data: any, flag: any) {
	const old = data;
	if (data == null || data == undefined) {
		return data;
	}
	if (typeof data == 'string') {
		data = parseFloat(data);
	}
	if (isNaN(data)) {
		return old;
	}

	let minute = 0;
	let second: string | number = 0;
	let millisecond: string | number = 0;

	if (flag == 'wm') {
		if (data >= 60000000) {
			minute = Math.floor(data / 60000000);
			second = (data % 60000000) / 1000000;
			if (second != 0) {
				second = ((data % 60000000) / 1000000).toFixed(2);
				return minute + 'm' + second + 's';
			} else {
				return minute + 'm';
			}
		} else if (data > 1000000 && data < 60000000) {
			second = Math.floor(data / 1000000);
			millisecond = ((data % 1000000) / 1000000).toFixed(2);
			let num = (parseFloat(String(second)) + parseFloat(millisecond)).toFixed(2);
			return num + 's';
		} else {
			//毫秒计算，借用秒
			second = Math.floor(data / 1000);
			millisecond = ((data % 1000) / 1000).toFixed(2);
			let num = (parseFloat(String(second)) + parseFloat(millisecond)).toFixed(2);
			return num + 'ms';
		}
	} else {
		if (data >= 60000) {
			minute = Math.floor(data / 60000);
			second = (data % 60000) / 1000;
			if (second != 0) {
				second = ((data % 60000) / 1000).toFixed(2);
				return minute + 'm' + second + 's';
			} else {
				return minute + 'm';
			}
		} else if (data >= 1000 && data < 60000) {
			second = Math.floor(data / 1000);
			millisecond = ((data % 1000) / 1000).toFixed(2);
			let num = (parseFloat(String(second)) + parseFloat(millisecond)).toFixed(2);
			return num + 's';
		} else {
			let str = data.toFixed(2);
			return str + 'ms';
		}
	}
}

/**
 * 生成随机uuid
 *  */
export function randomUUID() {
	const s: any[] = [];
	const hexDigits = '0123456789abcdef';
	for (let i = 0; i < 36; i++) {
		s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
	}
	s[14] = '4';
	s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
	s[8] = s[13] = s[18] = s[23] = '-';
	return s.join('');
}

/**
 *加密处理
 */
export function encryption(params: any) {
	const { data, type, param, key } = params;
	const result = JSON.parse(JSON.stringify(data));
	if (type === 'Base64') {
		param.forEach((ele: any) => {
			result[ele] = btoa(result[ele]);
		});
	} else {
		param.forEach((ele: any) => {
			const data = result[ele];
			const aseKey = CryptoJS.enc.Latin1.parse(key);
			const iv = aseKey;
			// 加密
			const encrypted = CryptoJS.AES.encrypt(data, aseKey, {
				iv: iv,
				mode: CryptoJS.mode.CFB,
				padding: CryptoJS.pad.NoPadding,
			});
			result[ele] = encrypted.toString();
		});
	}
	return result;
}

/**
 * 通过时间标签刻度间隔分割时间范围并进行补零
 * @param startTime 开始时间
 * @param endTime 结束时间
 * @param labelTimeLen 时间标签刻度间隔(分钟)
 * @param dataMap 数据映射
 */
export function splitTimeRangeAndCompleZero2(startTime: string, endTime: string, labelTimeLen: number, dataMap: any, delayTime: number) {
	if (labelTimeLen === undefined) {
		labelTimeLen = 10;
	}
	// startTime = startTime;
	// endTime = endTime;

	let startUsec = new Date(startTime).getTime();
	const endUsec = new Date(endTime).getTime();
	const stepUsec = labelTimeLen * 60 * 1000;
	const labelTimeArr = [],
		valueArr = [];

	while (endUsec > startUsec) {
		const k = parseTime(startUsec, '{h}:{i}');
		labelTimeArr.push(k);
		if (dataMap[k] !== undefined && dataMap[k] !== null) {
			valueArr.push(dataMap[k]);
		} else {
			// 补零
			valueArr.push(0);
		}
		startUsec += stepUsec;
	}

	if (labelTimeArr.length > 0 && valueArr.length > 0) {
		// 去掉最后一个点，防止掉底
		labelTimeArr.pop();
		valueArr.pop();
	}

	// 考虑到任务延迟的问题，如果倒数第二个点与当前时间相差在延迟时间范围内并且是实际数据，也将其去掉
	if (delayTime !== null && delayTime !== undefined) {
		if (labelTimeArr.length > 0 && valueArr.length > 0) {
			const currentDate = new Date();
			const currentUsec = currentDate.getTime();
			const tLabelTime = labelTimeArr[labelTimeArr.length - 1];
			const tt = new Date(startTime.substr(0, 10) + ' ' + tLabelTime + ':00').getTime();
			if (dataMap[tLabelTime] !== undefined && currentUsec - tt < delayTime * 2 * 60 * 1000) {
				labelTimeArr.pop();
				valueArr.pop();
			}
		}
	}

	return {
		labelTimeArr: labelTimeArr,
		valueArr: valueArr,
	};
}

/**
 * 通过时间标签刻度间隔分割时间范围并进行补零
 * @param startTime 开始时间
 * @param endTime 结束时间
 * @param labelTimeLen 时间标签刻度间隔(分钟)
 * @param dataMap 数据映射
 */
export function splitTimeRangeAndCompleZero(startTime: string, endTime: string, labelTimeLen: number, dataMap: any, isLastShow: boolean) {
	if (labelTimeLen === undefined) {
		labelTimeLen = 10;
	}
	// startTime = startTime;
	// endTime = endTime;

	let startUsec = new Date(startTime.replace(new RegExp(/-/gm), '/')).getTime();
	const endUsec = new Date(endTime.replace(new RegExp(/-/gm), '/')).getTime();
	const stepUsec = labelTimeLen * 60 * 1000;
	const labelTimeArr = [],
		valueArr = [];

	while (endUsec >= startUsec) {
		const k = parseTime(startUsec, '{h}:{i}');
		labelTimeArr.push(k);
		if (dataMap[k] !== undefined && dataMap[k] !== null) {
			valueArr.push(dataMap[k]);
		} else {
			// 补零
			valueArr.push(0);
		}
		startUsec += stepUsec;
	}

	// if (!isLastShow) {
	// 去掉最后一个点，保证不掉底
	// valueArr.pop();
	// labelTimeArr.pop();
	// }

	return {
		labelTimeArr: labelTimeArr,
		valueArr: valueArr,
	};
}

/**
 * 根据后端返回的流下载文件
 */
export function downloadFromBlob(blob: any, excelName: string, fullName?: string) {
	const o = {
		flag: false,
		msg: '',
	};
	return new Promise((resolve: (param: any) => void, reject) => {
		if (blob.type === 'application/json') {
			blob.text().then((txt: any) => {
				const json = JSON.parse(txt);
				o.flag = false;
				o.msg = json.msg;
				resolve(o);
			});
		} else {
			console.log('else---', blob);
			const blobURL = window.URL.createObjectURL(blob);
			const a = document.createElement('a');
			a.download = fullName || excelName + '_' + parseTime(new Date(), '{y}{m}{d}{h}{i}{s}') + '.xlsx';
			a.href = blobURL;
			a.style.display = 'none';
			document.body.appendChild(a);
			a.click();
			document.body.removeChild(a);
			o.flag = true;
			o.msg = 'success';
			resolve(o);
		}
	});
}

/**
 *  防抖
 */
export function debounce(func: () => any, wait: number, immediate?: boolean) {
	let timeout: any, args: any, context: any, timestamp: any, result: any;

	const later = function () {
		// 据上一次触发时间间隔
		const last = +new Date() - timestamp;

		// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
		if (last < wait && last > 0) {
			timeout = setTimeout(later, wait - last);
		} else {
			timeout = null;
			// 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
			if (!immediate) {
				result = func.apply(context, args);
				if (!timeout) context = args = null;
			}
		}
	};

	return function (...args: any) {
		context = window;
		timestamp = +new Date();
		const callNow = immediate && !timeout;
		// 如果延时不存在，重新设定延时
		if (!timeout) timeout = setTimeout(later, wait);
		if (callNow) {
			result = func.apply(context, args);
			context = args = null;
		}

		return result;
	};
}

/**
 * 防抖检查
 * @param config 防抖配置
 * @returns {boolean} true为通过检查，false为不通过
 */
export function checkDebounce(config: anyObj) {
	if (config.flag) {
		config.flag = false;
		setTimeout(function () {
			config.flag = true;
		}, config.time);
		return true;
	}
	return false;
}

/* @param config 归并配置
 *          data               要归并的数据集（必须）
 *          startTime          趋势图开始时间（必须）
 *          endTime            趋势图结束时间（必须）
 *          fields             要归并的字段（必须）
 *          scale              刻度（可选，如果不传或小于等于０，会自动生成刻度）
 *          labelTimeFormatter 时间标签格式化：{y}-{m}-{d} {h}:{i}:{s}，默认是{h}:{i}，也可以是自定义的格式化函数（可选）
 *          cycleTimeKey       时间周期字段名，默认是cycleTime（可选）
 *          isLastShow         是否展示最后一个点的标识
 */
export function mergeTrendData(config: any) {
	console.log(' mergeTrendData', config);
	/* eslint-disable */
	// 1、接收参数、校验
	const data = config.data,
		startTime = config.startTime,
		endTime = config.endTime,
		fields = config.fields,
		labelTimeFormatter = config.labelTimeFormatter;
	// isLastShow = config.isLastShow;
	let scale = config.scale;
	let trendSelfAdaptive = false;
	let labelTimePattern: string | undefined = '{h}:{i}';
	let AllLabelTimePattern: string | undefined = '{y}-{m}-{d} {h}:{i}';
	let cycleTimeKey = 'cycleTime';
	if (data === undefined || data === null || data.length <= 0) {
		throw Error('要归并的数据集为空');
	}
	if (startTime === undefined || startTime === null || startTime === '') {
		throw Error('开始时间不能为空');
	}
	if (endTime === undefined || endTime === null || endTime === '') {
		throw Error('结束时间不能为空');
	}
	if (fields === undefined || fields === null || fields.length <= 0) {
		throw Error('不存在要归并的字段');
	}
	// 校验刻度值，如果没有设置或小于等于0，自动启用刻度自适应
	if (scale === undefined || scale === null || scale <= 0) {
		trendSelfAdaptive = true;
	}
	// 设置时间标签格式化
	if (typeof labelTimeFormatter === 'string') {
		labelTimePattern = labelTimeFormatter;
	} else if (typeof labelTimeFormatter === 'function') {
		labelTimePattern = undefined;
	}
	// 设置时间周期字段名
	if (config.cycleTimeKey !== undefined && config.cycleTimeKey !== null) {
		cycleTimeKey = config.cycleTimeKey;
	}

	// 2、如果启动刻度自适应，则根据开始结束时间生成合适的刻度值
	const startTimeUsec = new Date(startTime.replace(/-/g, '/')).getTime();
	let endTimeUsec = new Date(endTime.replace(/-/g, '/')).getTime();

	if (trendSelfAdaptive) {
		const timeSpan = endTimeUsec - startTimeUsec;
		const m30Usec = 30 * 60 * 1000,
			h1Usec = 2 * m30Usec,
			h3Usec = 3 * h1Usec,
			h6Usec = 6 * h1Usec,
			h12Usec = 12 * h1Usec,
			h18Usec = 18 * h1Usec,
			h24Usec = 24 * h1Usec;
		if (timeSpan <= m30Usec) {
			// 小于等于30分钟，刻度设置为1，刻度数量：[0, 30]
			scale = 1;
		} else if (timeSpan <= h3Usec) {
			// 大于30分钟，小于等于3小时，刻度设置为5，刻度数量：[6, 36]
			scale = 5;
		} else if (timeSpan <= h6Usec) {
			// 大于3小时，小于等于6小时，刻度设置为10，刻度数量：[18, 36]
			scale = 10;
		} else if (timeSpan <= h12Usec) {
			// 大于6小时，小于等于12小时，刻度设置为15，刻度数量：[24, 48]
			scale = 15;
		} else if (timeSpan <= h18Usec) {
			// 大于12小时，小于等于18小时，刻度设置为20，刻度数量：[36, 54]
			scale = 20;
		} else if (timeSpan <= h24Usec) {
			// 大于18小时，小于等于24小时，刻度设置为25，刻度数量：[43, 57]
			scale = 25;
		} else {
			// 大于24小时，刻度统一设置为30
			scale = 30;
		}
	}

	// 3、根据开始结束时间、刻度生成时间轴
	const scaleUsec = scale * 60 * 1000,
		labelTimeArr: any[] = [],
		labelTimeUsecArr: any[] = [];
	let tempTimeUsec = startTimeUsec;

	while (tempTimeUsec <= endTimeUsec) {
		labelTimeArr.push(parseTime(tempTimeUsec, '{y}-{m}-{d} {h}:{i}:{s}'));
		labelTimeUsecArr.push(tempTimeUsec);
		tempTimeUsec += scaleUsec;
	}

	// 4、生成要合并的字段结果集
	const resFieldMap: anyObj = {};
	fields.forEach((field: any) => {
		resFieldMap[field.name + 'Arr'] = [];
	});

	// 5、归并数据，默认往前归并
	const resLabelTimeArr = [];
	const allResLabelTimeArr = []; //年月日时分

	let inx = 0;
	data.forEach((d: any) => {
		const cycleTimeUsec = new Date(d[cycleTimeKey].substring(0, 19).replace(/-/g, '/')).getTime();
		while (cycleTimeUsec >= labelTimeUsecArr[inx]) {
			console.log('labelTimeFormatter', labelTimeFormatter);
			console.log('abelTimePattern', labelTimePattern);
			if (labelTimePattern === undefined) {
				// 时间标签格式化函数
				resLabelTimeArr.push(labelTimeFormatter(labelTimeArr[inx], inx));
			} else {
				resLabelTimeArr.push(parseTime(labelTimeArr[inx], labelTimePattern));
			}
			allResLabelTimeArr.push(parseTime(labelTimeArr[inx], AllLabelTimePattern));
			for (let key in resFieldMap) {
				resFieldMap[key].push(0);
			}
			inx++;
		}
		fields.forEach((field: any) => {
			// 非自定义计算函数，默认归并相加
			if (field.calculate === undefined) {
				resFieldMap[field.name + 'Arr'][resLabelTimeArr.length - 1] += d[field.name];
			}
		});
	});

	// 6、补全时间轴，防止断数据时能补刻度
	while (inx < labelTimeArr.length) {
		if (labelTimePattern === undefined) {
			// 时间标签格式化函数
			resLabelTimeArr.push(labelTimeFormatter(labelTimeArr[inx], inx));
		} else {
			resLabelTimeArr.push(parseTime(labelTimeArr[inx], labelTimePattern));
		}
		allResLabelTimeArr.push(parseTime(labelTimeArr[inx], AllLabelTimePattern));
		for (let key in resFieldMap) {
			resFieldMap[key].push(0);
		}
		inx++;
	}

	// 7、处理自定义归并计算函数
	fields.forEach((field: any) => {
		if (typeof field.calculate === 'function') {
			for (let i = 0; i < inx; i++) {
				resFieldMap[field.name + 'Arr'][i] = field.calculate(resFieldMap, i);
			}
		}
	});
	/* eslint-disable */

	//判断是否展示最后一个点
	// if (!isLastShow) {
	//   // 8、如果刻度小于等于30，去掉最后一个点
	//   if (scale <= 30 && resLabelTimeArr.length > 0) {
	//
	//     for (let key in resFieldMap) {
	//       resFieldMap[key].pop();
	//     }
	//   }

	//   // 9、如果刻度等于60，去掉最后一个点
	//   if (scale == 60 && resLabelTimeArr.length > 0) {
	//     resLabelTimeArr.pop();
	//     for (let key in resFieldMap) {
	//       resFieldMap[key].pop();
	//     }
	//   }
	// }
	// 去掉最后一个
	resLabelTimeArr.pop();

	// 9、返回归并结果集
	return {
		resLabelTimeArr,
		allResLabelTimeArr,
		resFieldMap,
	};
}

// form表单提交,用于3.0跳转老项目
export function simulateFormSubmit(url: string, params: anyObj, blankFlag: string, method: string) {
	if (url === undefined || url === '' || params === undefined) {
		return;
	}
	const form = document.createElement('form');
	form.setAttribute('style', 'display:none');
	if (blankFlag === '1') {
		form.target = '_blank';
	}
	if ('get' === method) {
		form.method = 'get';
	} else {
		form.method = 'post';
	}
	form.action = url;
	params.forEach((item: anyObj) => {
		const inputData = document.createElement('input');
		inputData.type = 'hidden';
		inputData.name = item.name;
		inputData.value = item.value;
		form.append(inputData);
	});
	document.getElementsByTagName('body')[0].append(form);
	form.submit();
}

/**
 * 复制
 * @param msg 复制的内容
 * @return true: 复制成功 false: 复制失败
 */
export function copyMsg(msg: string) {
	const tempInput = document.createElement('textarea');
	tempInput.value = msg;
	document.body.appendChild(tempInput);
	tempInput.select();
	const copyFlag = document.execCommand('Copy');
	tempInput.remove();
	return copyFlag;
}

// 获取关系图最后一个节点
export function getLastNodeArr(edges: any, nodes: any) {
	let result = [];

	if (edges instanceof Array && edges.length) {
		// 假设数组第一项为关系图的最后一项
		let lastNodeId: any = edges[0].source;
		// 存储出现过的节点id
		let idsSet: Set<any[]> = new Set([]);
		let lastNodeIds: any[] = [];

		getLastNodeIds();

		function getLastNodeIds() {
			idsSet.add(lastNodeId);
			let count = 0;
			for (let i = 0; i < edges.length; i++) {
				// 如果数组里面有source等于lastNodeId,且当前项的target从来没在关系图出现（避免 1-2，2-1的情况） 将当前项的target设置为新的最后一项
				if (edges[i].source == lastNodeId && !idsSet.has(edges[i].target)) {
					// console.log("if",lastNodeId)
					lastNodeId = edges[i].target;
					// lastNodeIndex = i;
					idsSet.add(lastNodeId);
					getLastNodeIds();
					count++;
				}
				// console.log("lastnode",lastNodeId)
			}
			// console.log("count",count)
			// console.log(" lastNodeIndex ", lastNodeIndex)
			// 数组遍历玩还没有找到下一个节点，说明这个就是最后一个节点
			if (count == 0) {
				lastNodeIds.push(lastNodeId);
			}
		}
		result = nodes.filter((item: any) => lastNodeIds.indexOf(item.id) > -1);
		console.log('lastNodeIds', lastNodeIds);
	}

	return result;
}

/**
 * 判断两个对象是否有相同的key,以及相同的key值是否相同
 * @param  { object } query
 * @param  { object } lastQuery
 * @return { boolean }
 */
export function isSameObect(query: any, lastQuery: any) {
	// console.log('query',query)
	// console.log('lastquery',lastQuery)
	let arr = Object.keys(query);
	let arr2 = Object.keys(lastQuery);
	// 都是空对象，没变化
	if (JSON.stringify(query) == '{}' && JSON.stringify(lastQuery) == '{}') return true;

	// key的长度不相等返回false
	if (arr.length !== arr2.length) return false;

	for (let i = 0; i < arr.length; i++) {
		if (query[arr[i]] instanceof Object) {
			// 如果是对象或者数组就转成json字符串再对比
			let a = JSON.stringify(query[arr[i]]);
			let b = JSON.stringify(lastQuery[arr[i]]);
			if (a != b) return false;
		} else {
			// 如果有不同的key。说明对象有变化
			if (lastQuery.hasOwnProperty(arr[i]) === false) {
				return false;
			}
			// 如果有不同的值。说明对象有变化
			if (lastQuery[arr[i]] !== query[arr[i]]) {
				return false;
			}
		}
	}
	return true;
}
/**
 * 字符串换行
 * @param str 需换行的字符串
 * @param lineLen 每行字符个数
 * @param maxLine 最大行数，若指定，超出最大行数时会添加省略号。若不指定，一直换行到末尾
 * @param ellipsisLen 省略号留空长度，不传默认为2
 * @param feedSign 换行符，不传默认为\n
 * @returns {string}
 */
export function lineFeed(str: string, lineLen: number, maxLine: number, ellipsisLen = 2, feedSign = '\n') {
	let label = '',
		totalLen = str.length,
		totalLine = 1;
	for (let i = 0; i < totalLen; i++) {
		label += str.charAt(i);
		if ((i + 1) % lineLen === 0) {
			label += feedSign;
			totalLine++;
		}
		if (maxLine && totalLine >= maxLine) {
			// 如果有指定最大行数且当总行数大于最大行数时，判断剩余字符是否需要省略号
			if (lineLen >= totalLen - (i + 1)) {
				label += str.substring(i + 1);
			} else {
				label += str.substring(i + 1, i + 1 + lineLen - ellipsisLen); // 减ellipsisLen是为了给省略号留空间
				label += '...';
			}
			break;
		}
	}
	return label;
}

/**
 * This is just a simple version of deep copy
 * Has a lot of edge cases bug
 * If you want to use a perfect deep copy, use lodash's _.cloneDeep
 * @param {Object} source
 * @returns {Object}
 */
export function deepCloneOps(source: any) {
	if (!source && typeof source !== 'object') {
		throw new Error('error arguments');
	}
	const targetObj: any = source.constructor === Array ? [] : {};
	Object.keys(source).forEach((keys) => {
		if (source[keys] && typeof source[keys] === 'object') {
			targetObj[keys] = deepClone(source[keys]);
		} else {
			targetObj[keys] = source[keys];
		}
	});
	return targetObj;
}

/**
 * 表格时间格式化
 */
export function formatDate(cellValue: string | Date) {
	if (cellValue == null || cellValue == '') return '';
	let date = new Date(cellValue);
	let year = date.getFullYear();
	let month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
	let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
	let hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
	let minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
	let seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
	return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
}
/**
 * 表格时间格式化
 */
export function getDefaultDate(type: string = 'time') {
	let date = new Date();
	let year = date.getFullYear();
	let month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
	let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
	let hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
	let minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
	// let seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
	let seconds = '00';
	if (type === 'day') {
		return year + '-' + month + '-' + day + ' ' + '00:00:00';
	}
	return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
}
export function getDefaultLast1hDate(last: number) {
	let date = new Date();
	let year = date.getFullYear();
	let month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
	let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
	let hours = date.getHours() - last < 10 ? '0' + (date.getHours() - last) : date.getHours() - last;
	let minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
	// let seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
	let seconds = '00';
	return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
}
export function objToform(obj: Record<string, any>) {
	if (obj instanceof Object === false) return;
	const result: any[] = [];
	Object.keys(obj).forEach((ele) => {
		result.push(`${ele}=${obj[ele]}`);
	});
	return result.join('&');
}

/**
 * 将树状数据处理成graph需要的数据
 * @param arr graph原始数据 必须
 * @param d 最终返回的结果 非必须
 * @param idKey id的key 非必须
 * @returns d
 */
export function formatGraphData(
	arr: any[],
	d: GraphData = {
		nodes: [],
		edges: [],
	},
	idKey = 'id'
) {
	if (arr instanceof Array === false) {
		console.error('arr不是数组---------');
		return d;
	}
	arr.forEach((node: any) => {
		node[idKey] = node[idKey] + '';
		let index = d.nodes.findIndex((n) => n[idKey] === node[idKey]);
		if (index === -1) {
			// 没有的节点才加进去
			d.nodes.push(node);
		}
		if (node.childNodes instanceof Array) {
			node.childNodes.forEach((subNode: any) => {
				d.edges.push({
					source: node[idKey] + '',
					target: subNode[idKey] + '',
				});
			});
			formatGraphData(node.childNodes, d);
		}
	});
	return d;
}

/**
 * 列表排序
 * @param params 查询参数
 * @param column 排序字段信息
 * @param execute 查询方法
 */
export function tableSort(params: anyObj, column: anyObj, execute: () => void) {
	let fieldName = column.prop;
	let sortingType = column.order;
	if (!sortingType) {
		params.isAsc = null;
		fieldName = null;
	}
	if (sortingType == 'descending') {
		params.isAsc = 'desc';
	}
	if (sortingType == 'ascending') {
		params.isAsc = 'asc';
	}
	params.orderByColumn = fieldName;
	execute();
}
export function mapFilter(arr: any[] | anyObj, params: string) {
	return arr.map((opt: anyObj) => opt[params]);
}

// 根据后端返回的流下载文件
export function downloadCustom(blob: any, fileName: string, type: string) {
	const o = {
		flag: false,
		msg: '',
	};
	return new Promise((resolve, reject) => {
		if (blob.type === 'application/json') {
			blob.text().then((txt: any) => {
				const json = JSON.parse(txt);
				o.flag = false;
				o.msg = json.msg;
				resolve(o);
			});
		} else {
			const reader = new FileReader();
			reader.readAsDataURL(blob);
			reader.onload = (e: any) => {
				const a: any = document.createElement('a');
				a.download = fileName + '.' + type;
				a.href = e.target.result;
				a.style.display = 'none';
				document.body.appendChild(a);
				a.click();
				document.body.removeChild(a);
			};
			o.flag = true;
			o.msg = 'success';
			resolve(o);
		}
	});
}

// 格式化字节
export function formatBytes(value: number | string, hasUnit: boolean = true) {
	let n = Number(value);
	let res;
	let unit; //单位
	if (Number.isNaN(n)) {
		return 0;
	}
	if (n >= 1024 * 1024 * 1024) {
		unit = 'GB';
		// 保留两位小数
		res = Math.floor((n / (1024 * 1024 * 1024)) * 100) / 100;
	} else if (n >= 1024 * 1024) {
		unit = 'MB';
		// 保留两位小数
		res = Math.floor((n / (1024 * 1024)) * 100) / 100;
	} else if (n >= 1024) {
		unit = 'KB';
		// 保留两位小数
		res = Math.floor((n / 1024) * 100) / 100;
	} else {
		unit = 'B';
		res = n;
	}
	return hasUnit ? res + unit : res;
}

/**
 * 解决处理toFixed()在尾数为5的情况下偶尔出现不会四舍五入情况
 * @param val 需要处理的数据
 * @param num 保留几位小数
 * @returns 将处理后的数返回
 */
export function myFixed(val: number, num: number): number | string {
	// 再四舍五入取整，因为toFixed有四舍五入 * 要取多少位小数，先乘10的多少次方 / 再除以10的多少次方就是保留多少位的小数了
	return (Math.round((val + Number.EPSILON) * Math.pow(10, num)) / Math.pow(10, num)).toFixed(num);
}
/**
 *
 * @param data
 * @returns
 */
export function commonFormatter(data: any, unit?: string) {
	const old = data;
	if (data == null || data == undefined) {
		return data;
	}
	if (typeof data == 'string') {
		data = parseFloat(data);
	}
	if (isNaN(data)) {
		return old;
	}
	let units = unit;
	if (units === 'bps') {
		if (data >= 1000000000) {
			// 如果比特率大于等于 1 Gbps
			data = data / 1000000000;
			units = 'Gbps';
		} else if (data >= 1000000) {
			// 如果比特率大于等于 1 Mbps
			data = data / 1000000;
			units = 'Mbps';
		} else if (data >= 1000) {
			// 如果比特率大于等于 1 kbps
			data = data / 1000;
			units = 'Kbps';
		}
	} else if (units === 'B') {
		if (data >= 1024 * 1024 * 1024) {
			// 如果字节数大于等于 1 GB
			data = data / (1024 * 1024 * 1024);
			units = 'GB';
		} else if (data >= 1024 * 1024) {
			// 如果字节数大于等于 1 MB
			data = data / (1024 * 1024);
			units = 'MB';
		} else if (data >= 1024) {
			// 如果字节数大于等于 1 KB
			data = data / 1024;
			units = 'KB';
		}
	} else if (units === '个' || units === '次' || units === '项') {
		if (data >= 1000) {
			// 如果数量大于等于 1000
			data = data / 1000;
			units = `K ${units}`;
		}
	}

	return myFixed(data, 2) + ' ' + units;
}

/**
 * 指定时间内往前减去指定分钟
 * @param minutes 分钟
 * @param targetTime 指定时间
 * @returns 减去10分钟的时间
 */
export function calculateTimeBefore(minutes: number | any, targetTime: string, type: string = 'time') {
	let targetDateTime;

	if (targetTime) {
		targetDateTime = new Date(targetTime);
	} else {
		if (type === 'day') {
			targetDateTime = new Date(getDefaultDate('day'));
		} else if (type === 'last1h') {
			targetDateTime = new Date(getDefaultLast1hDate(1));
		} else {
			targetDateTime = new Date(getDefaultDate());
		}
	}
	// 计算目标时间往前推指定分钟数后的时间
	if (typeof minutes === 'number') {
		if (type === 'day') {
			return parseTime(targetDateTime, '{y}-{m}-{d} {h}:{i}:{s}');
		}
		const calculatedTime = new Date(targetDateTime.getTime() - minutes * 60000);
		return parseTime(calculatedTime, '{y}-{m}-{d} {h}:{i}:{s}');
	}
	return targetTime;
}

type Type = 1 | 2 | 3 | 4;
interface ResObj {
	color: string;
	width: number;
}
/**
 * 根据不同情况条件获取进度条的背景色和百分比值
 * @param type 进度条类型 1、成功率相关。2、中断次数。3、其他耗时相关（微秒） 4、中段耗时（分钟）
 * @param value 数值 百分比 | 次数 | 微妙
 * @returns 进度条背景色color,和百分比值
 */
export function getValueBasedOnColor(type: Type, value: number): ResObj {
	let colors = ['#1DC69D', '#FE9A0C', 'red', '#9A54F2'];
	let color = '';
	let width = 0;
	if (type === 1) {
		switch (true) {
			case value >= 95:
				color = colors[0];
				break;
			case value >= 85:
				color = colors[1];
				break;
			default:
				color = colors[2];
		}
		width = value;
		return {
			color,
			width,
		};
	} else if (type === 2) {
		switch (true) {
			case value >= 100:
				color = colors[2];
				break;
			case value >= 60:
				color = colors[1];
				break;
			default:
				color = colors[3];
		}
		width = value / 1000;
		return {
			color,
			width,
		};
	} else if (type === 3) {
		switch (true) {
			case value >= 1000000:
				color = colors[2];
				break;
			case value >= 500000:
				color = colors[1];
				break;
			default:
				color = colors[0];
		}
		width = value / 20000;
		return {
			color,
			width,
		};
	} else if (type === 4) {
		switch (true) {
			case value >= 100:
				color = colors[3];
				break;
			case value >= 60:
				color = colors[1];
				break;
			default:
				color = colors[3];
		}
		width = value / 1000;
		return {
			color,
			width,
		};
	}
	return {
		color,
		width: value,
	};
}

/**
 * 通过某属性对list集合去重
 * @param list 集合数据
 * @param field 字段、属性，通过它进行去重
 * @returns T[]，返回去重后的集合
 */
export function uniqueCommon<T extends any[], K extends keyof T[number], L extends T[number]>(list: T, field: K): T[] {
	return Array.from(new Set(list.map((items: L) => items[field]))).map((v: K) => {
		return list.find((item: L) => item[field] === v);
	});
}

/**
 * 用0替换数组或者对象的null
 * @param {*Array|Object} o
 */
export function replaceNullWithZero(o: any) {
	if (o instanceof Object === false) return;
	if (o instanceof Array) {
		o.forEach((item, index) => {
			if (item instanceof Object) {
				replaceNullWithZero(item);
			}
			if (item == null) {
				o[index] = 0;
			}
		});
	} else {
		for (let key in o) {
			if (o[key] instanceof Object) {
				replaceNullWithZero(o[key]);
			}
			if (o[key] == null) {
				o[key] = 0;
			}
		}
	}
}
/**
 * 通过时间标签刻度间隔分割时间范围并进行补零
 * @param startTime 开始时间
 * @param endTime 结束时间
 * @param labelTimeLen 时间标签刻度间隔(分钟)
 * @param data 原始数据
 * @param timeFormatStr 时间格式化字符串，默认"{h}:{i}"分秒
 * @param formatKeysArr 要格式化的项key，不传就返回格式化对象所有的key例如： ["currentValue"]
 */
export function splitTimeRangeAndCompleZero3(
	startTime: string,
	endTime: string,
	labelTimeLen: number,
	data: any[],
	timeFormatStr?: string,
	formatKeysArr?: any[]
) {
	labelTimeLen = labelTimeLen || 10;
	timeFormatStr = timeFormatStr || '{h}:{i}';
	let result: any = {
		labelTimeArr: [],
		o: {},
	};

	if (data instanceof Array === false || data.length === 0) return;

	// 处理原始数据的时间，作为key
	data.forEach((item) => {
		item.labelTime = parseTime(item.labelTime, timeFormatStr);
	});

	//用于存储处理后的数据
	const o: anyObj = {};
	// 对象的每一项生成处理后的数组
	if (!formatKeysArr && data[0]) {
		formatKeysArr = data[0];
	}

	Object.keys(formatKeysArr!).forEach((key) => {
		o[key + 'Arr'] = [];
	});

	let startUsec = new Date(startTime.replace(new RegExp(/-/gm), '/')).getTime();
	const endUsec = new Date(endTime.replace(new RegExp(/-/gm), '/')).getTime();
	const stepUsec = labelTimeLen * 60 * 1000;
	const labelTimeArr: any[] = [];

	while (endUsec >= startUsec) {
		let k = parseTime(startUsec, timeFormatStr);
		labelTimeArr.push(k);
		let obj = data.find((item) => item.labelTime === k) || {};

		Object.keys(formatKeysArr!).forEach((key) => {
			if (obj[key]) {
				o[key + 'Arr'].push(obj[key]);
			} else {
				// 没有数据补0
				o[key + 'Arr'].push(0);
			}
		});
		startUsec += stepUsec;
	}
	result.labelTimeArr = labelTimeArr;
	result.o = o;
	return result;
}
